﻿using System;
using System.Collections.Generic;

using System.Text;

namespace Sinacor.Tools.Negocio
{
    public class Mensagem : NegocioBase<Entidade.Mensagem>
    {
        protected Dado.Mensagem dados = null;
        protected Dado.TraducaoMensagem traducao = null;
        public override void incluir(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            byte? idExceptionMessage = null;
                        
            switch (entidade.TipoFiltroMensagem)
            {
                case Sinacor.Tools.Entidade.Enum.TipoFiltroMensagem.Mensagem:
                    Negocio.TextoMensagem texto = new TextoMensagem();

                    if (entidade.Traducao == null)
                        throw new Exception("O texto mensagem não foi informado");
                    else
                    {
                        if (texto.jaEstaCadastradaIdenticamente(entidade.Traducao))
                            throw new Exception("Este texto mensagem ja está cadastrado!");
                    }
                    entidade.Traducao.Idioma.Id = Negocio.Idioma.buscarIdIdiomaPadrao();
                    entidade.Traducao.IdMensagem = this.buscarProximoTextoId();

                    texto.incluir(entidade.Traducao);

                    inserirMensagem(entidade);       
                    
                    if (entidade.IDExceptionMessage.HasValue)
                    {   
                        Entidade.MensagemExcecao entidadeExM = new Entidade.MensagemExcecao();
                        Negocio.MensagemExcecao negocioExM = new Negocio.MensagemExcecao();
                        Dado.MensagemExcecao dadosExcM = new Dado.MensagemExcecao(); 


                        entidadeExM.Modulo = entidade.Modulo;
                        entidadeExM.Submodulo = entidade.Submodulo;
                        
                        entidadeExM.Mensagem = new Entidade.Mensagem(); 
                        entidadeExM.Mensagem.ResourceKey = entidade.ResourceKey.Replace("Message", "ExceptionMessage");
                        entidadeExM.Descricao  = entidade.Traducao.MensagemTraduzida; 

          
                        entidadeExM.Id = Negocio.Modulo.buscarProximoId(entidade.Modulo);
                        entidadeExM.Mensagem.Id = negocioExM.buscarIdResourceKey(entidadeExM);
                        
                        dadosExcM.incluir(entidadeExM);

                        entidade.IDException =entidadeExM.Id;
                        entidade.Traducao.IdMensagem = entidadeExM.Mensagem.Id;
                    }

                    break;
                case Sinacor.Tools.Entidade.Enum.TipoFiltroMensagem.ResouceKey:
                    inserirMensagem(entidade);                   
                    break;
                default:
                    break;
            }
        }

        public void inserirMensagem(Entidade.Mensagem entidade)
        {
            Negocio.TraducaoMensagem traducao = new TraducaoMensagem();
            
            this.validaInclusao(entidade);
            if (this.jaEstaCadastrada(entidade))
            {
                if (traducao.jaEstaCadastrada(entidade.Traducao, entidade))
                {
                    dados = new Dado.Mensagem();
                    entidade.Traducao.StatusTraducao.Id = Negocio.StatusTraducao.buscarIdStatusPadrao();
                    entidade.Id = this.buscarProximoId();
                    entidade.Traducao.IdMensagem = traducao.consultaCodigoTextoID(entidade.Traducao, entidade);
                }
                else
                {
                    Negocio.TextoMensagem texto = new TextoMensagem();
                    dados = new Dado.Mensagem();
                    entidade.Traducao.StatusTraducao.Id = Negocio.StatusTraducao.buscarIdStatusPadrao();
                    entidade.Id = this.buscarProximoId();
                    if (texto.jaEstaCadastradaIdenticamente(entidade.Traducao))
                    {
                        entidade.Traducao.IdMensagem = traducao.consultarID(entidade.Traducao, entidade);
                        if (entidade.Traducao.IdMensagem == null)
                        {
                            entidade.Traducao.IdMensagem = texto.ConsultaID(entidade.Traducao);
                        }
                    }
                    else
                    {
                        entidade.Traducao.IdMensagem = this.buscarProximoTextoId();
                        texto.incluir(entidade.Traducao);
                    }
                }
            }

            if (traducao.jaEstaCadastrada(entidade.Traducao, entidade))
            {
                dados = new Dado.Mensagem();
                entidade.Traducao.StatusTraducao.Id = Negocio.StatusTraducao.buscarIdStatusPadrao();
                entidade.Id = this.buscarProximoId();
                entidade.Traducao.IdMensagem = traducao.consultaCodigoTextoID(entidade.Traducao, entidade);
            }
            else
            {
                Negocio.TextoMensagem texto = new TextoMensagem();
                dados = new Dado.Mensagem();
                entidade.Traducao.StatusTraducao.Id = Negocio.StatusTraducao.buscarIdStatusPadrao();
                entidade.Id = this.buscarProximoId();
                if (texto.jaEstaCadastradaIdenticamente(entidade.Traducao))
                {
                    entidade.Traducao.IdMensagem = traducao.consultarID(entidade.Traducao, entidade);
                    if (entidade.Traducao.IdMensagem == null)
                    {
                        entidade.Traducao.IdMensagem = texto.ConsultaID(entidade.Traducao);
                    }
                }
                else
                {
                    entidade.Traducao.IdMensagem = this.buscarProximoTextoId();
                    texto.incluir(entidade.Traducao);
                }
            }
            
            dados.incluir(entidade);

            dados.incluirTraducao(entidade);

            if (entidade.IDExceptionMessage.HasValue)
            {
                entidade.TipoMensagem.Id = entidade.IDExceptionMessage.Value;
                entidade.Id = this.buscarProximoId();

                Entidade.Mensagem entidadeclone = (Entidade.Mensagem)entidade.Clone();
                entidadeclone.ResourceKey = entidade.ResourceKey.Replace("Message", "ExceptionMessage");

                dados.incluir(entidadeclone);

                dados.incluirTraducao(entidadeclone);

                entidade.ResourceKey2 = entidadeclone.ResourceKey;
            }
        }
        
        public override void alterar(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            Negocio.TraducaoMensagem traducao = new TraducaoMensagem();
            switch (entidade.TipoFiltroMensagem)
            {
                case Sinacor.Tools.Entidade.Enum.TipoFiltroMensagem.Mensagem:
                    
                    Negocio.TextoMensagem texto = new TextoMensagem();

                    if (entidade.Traducao == null)
                        throw new Exception("O texto mensagem não foi informado");
                    else
                    {
                        if (texto.jaEstaCadastradaIdenticamente(entidade.Traducao))
                            throw new Exception("Este texto mensagem já está cadastrado!");
                    }

                    texto.alterar(entidade.Traducao);
                    break;
                case Sinacor.Tools.Entidade.Enum.TipoFiltroMensagem.ResouceKey:

                    if (jaEstaCadastrada(entidade))
                    {
                        if (traducao.jaEstaCadastrada(entidade.Traducao, entidade))
                        {
                            dados = new Dado.Mensagem();
                            entidade.Traducao.StatusTraducao.Id = Negocio.StatusTraducao.buscarIdStatusPadrao();
                            entidade.Traducao.IdMensagem = traducao.consultaCodigoTextoID(entidade.Traducao, entidade);
                            //dados.alterar(entidade);
                            dados.alterarTraducao(entidade);
                        }
                        else
                        {
                            Negocio.TextoMensagem textoAlteracao = new TextoMensagem();
                            dados = new Dado.Mensagem();
                            entidade.Traducao.StatusTraducao.Id = Negocio.StatusTraducao.buscarIdStatusPadrao();
                            if (textoAlteracao.jaEstaCadastradaIdenticamente(entidade.Traducao))
                            {
                                if (traducao.jaEstaCadastrada(entidade.Traducao, entidade))
                                {
                                    entidade.Traducao.IdMensagem = traducao.consultarID(entidade.Traducao, entidade);
                                    dados.alterarTraducao(entidade);
                                }
                                else
                                {
                                    entidade.Traducao.IdMensagem = this.buscarProximoTextoId();
                                    dados.alterarTraducao(entidade);
                                }
                            }
                            else
                            {
                                entidade.Traducao.IdMensagem = this.buscarProximoTextoId();
                                textoAlteracao.incluir(entidade.Traducao);
                                dados = new Dado.Mensagem();
                                dados.alterarTraducao(entidade);
                            }
                        }
                        //throw new Exception("Esta ResourceKey já está cadastrada!");
                    }

                    Entidade.Mensagem entidadeclone = (Entidade.Mensagem)entidade.Clone();

                    if (entidade.IDExceptionMessage.HasValue)
                    {
                        entidadeclone.ResourceKey = entidade.ResourceKey.Replace("Message", "ExceptionMessage");

                        if (jaEstaCadastrada(entidadeclone))
                            throw new Exception("Esta mensagem já possui ExceptionMessage cadastrada!");
                    }
                    this.validaAlteracao(entidade);

                    dados = new Dado.Mensagem();
                    dados.alterar(entidade);
                    
                    if (entidade.IDExceptionMessage.HasValue)
                    {
                        entidadeclone.TipoMensagem.Id = entidade.IDExceptionMessage.Value;
                        entidadeclone.Id = this.buscarProximoId();

                        dados.incluir(entidadeclone);

                        dados.incluirTraducao(entidadeclone);

                        entidade.ResourceKey2 = entidadeclone.ResourceKey;
                        
                        Entidade.MensagemExcecao entidadeExM = new Entidade.MensagemExcecao();
                        Negocio.MensagemExcecao negocioExM = new Negocio.MensagemExcecao();
                        Dado.MensagemExcecao dadosExcM = new Dado.MensagemExcecao();
                        
                        entidadeExM.Modulo = entidade.Modulo;
                        entidadeExM.Submodulo = entidade.Submodulo;

                        entidadeExM.Mensagem = new Entidade.Mensagem();
                        entidadeExM.Mensagem.ResourceKey = entidade.ResourceKey.Replace("Message", "ExceptionMessage");
                        entidadeExM.Descricao = entidade.Traducao.MensagemTraduzida;


                        entidadeExM.Id = Negocio.Modulo.buscarProximoId(entidade.Modulo);
                        entidadeExM.Mensagem.Id = negocioExM.buscarIdResourceKey(entidadeExM);

                        dadosExcM.incluir(entidadeExM);

                        entidade.IDException = entidadeExM.Id;
                        entidade.Traducao.IdMensagem = entidadeExM.Mensagem.Id;
                    }

                    
                    break;
                default:
                    break;
            }
        }

        public override void deletar(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            if (!Permissoes.usuarioPossuiPermissaoRecurso("mensagem", "deletar", this.getUser(), this.getPermissionXmlPath()))
                throw new Exception("Usuário não cadastrado para esta operação!");
            this.validaDelecao(entidade);
            //if (possuiExcecaoCadastrada(entidade)) throw new Exception("Não é possível deletar esta mensagem pois está vinculada a uma exceção.");
            Negocio.TraducaoMensagem traducao = new TraducaoMensagem();
            entidade.Traducao.IdMensagem = entidade.Id;
            traducao.deletar(entidade.Traducao);

            dados = new Dado.Mensagem();
            dados.deletar(entidade);
        }

        public void deletarMensagem(Entidade.Mensagem entidade)
        {
            if (!Permissoes.usuarioPossuiPermissaoRecurso("mensagem", "deletar", this.getUser(), this.getPermissionXmlPath()))
                throw new Exception("Usuário não cadastrado para esta operação!");

            Negocio.TextoMensagem texto = new TextoMensagem();
            entidade.Traducao.IdMensagem = entidade.Id;
            entidade.Traducao.Idioma = new Entidade.Idioma();
            
            
            texto.deletar(entidade.Traducao);
        }

        public void deletarResourceKey(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            if (!Permissoes.usuarioPossuiPermissaoRecurso("mensagem", "deletar", this.getUser(), this.getPermissionXmlPath()))
                throw new Exception("Usuário não cadastrado para esta operação!");

            validaDelecao(entidade);
            
            traducao = new Dado.TraducaoMensagem();
            traducao.deletar(entidade.Traducao); 

            dados = new Dado.Mensagem();
            dados.deletar(entidade);
        }
        
        public bool possuiExcecaoCadastrada(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            dados = new Dado.Mensagem();
            return dados.possuiExcecaoCadastrada(entidade) == null ? false : true;
        }


        public void salvar(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            if (entidade.Id >= 0)
            {
                this.alterar(entidade);
            }
            else
            {
                this.incluir(entidade);
            }
        }

        public override List<Sinacor.Tools.Entidade.Mensagem> consultar(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            dados = new Dado.Mensagem();
            List<Sinacor.Tools.Entidade.Mensagem> lista = dados.consultar(entidade);
            lista.Sort(entidade);
            return lista;
        }

        public List<Sinacor.Tools.Entidade.Mensagem> ConsultarMensagemResourceKey(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            dados = new Dado.Mensagem();
            List<Sinacor.Tools.Entidade.Mensagem> lista = dados.ConsultarMensagemResourceKey(entidade);
            return lista;
        }

        public List<Sinacor.Tools.Entidade.Mensagem> consultarResourceKey(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            dados = new Dado.Mensagem();
            List<Sinacor.Tools.Entidade.Mensagem> lista = dados.consultarResourceKey(entidade);
            return lista;
        }
       
        public List<Sinacor.Tools.Entidade.Mensagem> consultarMensagem(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            dados = new Dado.Mensagem();
            List<Sinacor.Tools.Entidade.Mensagem> lista = dados.consultarMensagem(entidade);
            lista.Sort(entidade);
            return lista;
        }

        public bool jaEstaCadastrada(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            dados = new Dado.Mensagem();
            object retorno = dados.jaEstaCadastrada(entidade);
            return retorno == null ? false : true;
        }
        
        protected void validaDelecao(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            if (entidade.Id == null || entidade.Id < 0)
                throw new Exception("Campo Código obrigatório para deleção!");
        }

        protected void validaInclusao(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            string mensagem = string.Empty;
            if (string.IsNullOrEmpty(entidade.Proposito))
            {
                mensagem += "Campo Propósito obrigatório!" + Environment.NewLine;
            }

            if (entidade.StatusMensagem == null || entidade.StatusMensagem == null)
            {
                mensagem += "Campo Status da Mensagem obrigatório!" + Environment.NewLine;
            }

            if (entidade.TipoMensagem == null || entidade.TipoMensagem == null)
            {
                mensagem += "Campo Tipo da Mensagem obrigatório!" + Environment.NewLine;
            }
            
            if (string.IsNullOrEmpty(entidade.ResourceKey))
            {
                mensagem += "Campo Resource Key é obrigatório!" + Environment.NewLine;
            }

            if (string.IsNullOrEmpty(entidade.Modulo))
            {
                mensagem += "Campo Modulo é obrigatório!" + Environment.NewLine;
            }

            if (entidade.Modulo != "Common")
            {
                if (string.IsNullOrEmpty(entidade.Submodulo))
                {
                    mensagem += "Campo Submodulo é obrigatório!" + Environment.NewLine;
                }
            }

            if (entidade.Traducao == null || string.IsNullOrEmpty(entidade.Traducao.MensagemTraduzida))
            {
                mensagem += "Campo Mensagem é obrigatório!" + Environment.NewLine;
            }

            string statusPadrao = System.Configuration.ConfigurationManager.AppSettings["STATUSPADRAOMENSAGEM"];

            if ((!string.IsNullOrEmpty(statusPadrao)) && (entidade.StatusMensagem.Id != Convert.ToByte(statusPadrao)))
            {
                if (!Permissoes.usuarioPossuiPermissaoRecurso("mensagem", "alterarstatus", this.getUser(), this.getPermissionXmlPath()))
                    throw new Exception("Usuário não possui permissão para incluir o status da mensagem diferente do padrão!");
            } 

            if (mensagem != string.Empty)
                throw new Exception(mensagem);
            
        }

        protected void validaAlteracao(Sinacor.Tools.Entidade.Mensagem entidade)
        {
            string mensagem = string.Empty;
            if (entidade.Id < 0 || entidade.Id == null)
            {
                mensagem += "Campo Código obrigatório!" + Environment.NewLine;
            }

            if (entidade.StatusMensagem == null || entidade.StatusMensagem == null)
            {
                mensagem += "Campo Status da Mensagem obrigatório!" + Environment.NewLine;
            }

            if (entidade.TipoMensagem == null || entidade.TipoMensagem == null)
            {
                mensagem += "Campo Tipo da Mensagem obrigatório!" + Environment.NewLine;
            }

            if (string.IsNullOrEmpty(entidade.Proposito))
            {
                mensagem += "Campo Propósito obrigatório!" + Environment.NewLine;
            }

            if (string.IsNullOrEmpty(entidade.ResourceKey))
            {
                mensagem += "Campo Resource Key obrigatório!" + Environment.NewLine;
            }

            if (string.IsNullOrEmpty(entidade.Modulo))
            {
                mensagem += "Campo Modulo é obrigatório!" + Environment.NewLine;
            }

            if (entidade.Modulo != "Common")
            {
                if (string.IsNullOrEmpty(entidade.Submodulo))
                {
                    mensagem += "Campo Submodulo é obrigatório!" + Environment.NewLine;
                }
            }

            string statusPadrao = System.Configuration.ConfigurationManager.AppSettings["STATUSPADRAOMENSAGEM"];

            if ((!string.IsNullOrEmpty(statusPadrao)) && (entidade.StatusMensagem.Id != Convert.ToByte(statusPadrao)))
            {
                if (!Permissoes.usuarioPossuiPermissaoRecurso("mensagem", "alterarstatus", this.getUser(), this.getPermissionXmlPath()))
                    throw new Exception("Usuário não possui permissão para alterar o status da mensagem!");
            }            

            if (mensagem != string.Empty)
                throw new Exception(mensagem);
        }

        public int buscarProximoId()
        {
            object proximoId;
            lock (new object())
            {
                dados = new Dado.Mensagem();
                proximoId = dados.buscarProximoId();
                if (proximoId == null)
                    proximoId = 0;

                return Convert.ToInt32(proximoId);
            }
        }

        public int buscarProximoTextoId()
        {
            object proximoTextoId;
            lock (new object())
            {
                dados = new Dado.Mensagem();
                proximoTextoId = dados.buscarProximoTextoId();
                if (proximoTextoId == null)
                    proximoTextoId = 0;

                return Convert.ToInt32(proximoTextoId);
            }
        }


        public static int? buscarIdMensagemPadrao()
        {
            string idMensagem = System.Configuration.ConfigurationManager.AppSettings["CODIGOMENSAGEMPADRAO"];
            if (string.IsNullOrEmpty(idMensagem)) throw new Exception("Não existe mensagem padrão cadastrada no arquivo .config!");

            return Convert.ToInt32(idMensagem);
        }

    }
}
